home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 5 / QRZ Ham Radio Callsign Database - Volume 5.iso / files / tcpip / misc / tnc1stuf.lzh / NET_TNC.ARC / TNC1KISS.ASM < prev    next >
Encoding:
Assembly Source File  |  1987-06-12  |  24.4 KB  |  1,011 lines

  1.     title    "KISS - raw TNC handler"
  2.  
  3. * KISS - a SLIP handler for the TAPR TNC1
  4. * Written by Marc Kaufman, WB6ECE
  5. *    March 1987
  6. *
  7. * Copyright 1987 by Marc Kaufman, WB6ECE
  8. * All rights reserved
  9. *
  10. * Permission granted for noncommercial copying and use
  11. * provided this notice is retained.
  12.  
  13. * Correction History:
  14. *
  15. *    4/17/87    - mtk: Initial Release (1.0)
  16. *    4/19/87    - mtk: Improve handling of timer values that are  a
  17. *            multiple of 65536 E-clock ticks
  18. *    4/30/87 - mtk: Correct error in format of TNC->Host block
  19. *            by stuffing '0' before data
  20.  
  21. * Refer to Phil Karn's description of KISS for details
  22. *
  23. * The following frame types (Host to TNC) are supported:
  24. *
  25. *    0 Data        - data frame to HDLC channel
  26. *    1 TXDelay    - 0 <= TXDelay  <= 255 (* 10 ms.)
  27. *    2 Peristence    - 255 -> transmit now
  28. *    3 SlotTime    - 0 <= SlotTime <= 255 (* 10 ms.)
  29. *    4 TXTail    - 0 <= TXTail   <= 255 (* 10 ms.)
  30. *    5 HDX/FDX    - 0 = HDX, 1 = FDX
  31. *    6 Speed        -     0 < Speed <=     24 (slow TNC)
  32. *            - 128+0 < Speed <= 128+48 (fast TNC)
  33. *    DEBUG        - do swi to monitor if command==DEBUG
  34. *
  35. *    The Speed parameter sets the HDLC baud rate to (Speed*300) baud.
  36. *    The high order bit (128), if set, indicates that the TNC1 is
  37. *     running with a 2x clock.  Maximum baud rates are 7200 for the slow
  38. *     TNC, and 14400 for the fast TNC.
  39.  
  40. * The following frame types (TNC to Host) are supported:
  41. *
  42. *    0 Data        - data frame from HDLC channel
  43.  
  44. * The normal idle state for the async receiver is "waiting for command"
  45. *  after the trailing FEND from the previous packet.  Hence, to enter
  46. *  debugging mode, it is only necessary to connect the terminal to the
  47. *  TNC directly and send the DEBUG character..
  48.  
  49. * Debugging flag - I set this to Ctl-Q ($11) when I want debugging on
  50.  
  51. DEBUG    equ    0        Debug turned off
  52. *DEBUG    equ    $11        Debug turned on
  53.  
  54. * Hardware addresses
  55.  
  56. ***        6551 UART - initial setup by loader
  57.  
  58. acia    equ    $2010        base address
  59. acchar    equ    acia
  60. acstat    equ    acia+1
  61. accmnd    equ    acia+2
  62. acctrl    equ    acia+3
  63.  
  64. as_fram    equ    $02        framing error only
  65. as_err    equ    $07        parity, framing, and overrun errors
  66. as_rdr    equ    $08        receive data register full
  67. as_xmt    equ    $10        xmit data register empty
  68. as_irq    equ    $80        acia interrupt request
  69.  
  70. ac_dis    equ    $0a        disable transmitter and receiver, set RTS
  71. ac_enb    equ    $09        enable receiver interrupts, set RTS
  72. ac_xmt    equ    $05        enable transmit and receive interrupts
  73.  
  74. ***        6520 parallel i/o chip -- not used
  75.  
  76. pia    equ    $2020        base address
  77. pra    equ    pia        register A
  78. pcra    equ    pia+1        control A
  79. prb    equ    pia+2        register B
  80. pcrb    equ    pia+3        control B
  81.  
  82. ***        6522 peripheral timer and i/o chip
  83.  
  84. via    equ    $2040        base address
  85. vorb    equ    via        output register B
  86. vora    equ    via+15        output register A, no handshake
  87. vddrb    equ    via+2        data direction register B
  88. vddra    equ    via+3        data direction register A
  89. vtim1cl    equ    via+4        low byte of timer 1 counter
  90. vtim1ch    equ    via+5        high byte of timer 1 counter
  91. vtim1ll    equ    via+6        low byte of timer 1 latch
  92. vtim1lh    equ    via+7        high byte of timer 1 latch
  93. vtim2l    equ    via+8        low byte of timer 2
  94. vtim2h    equ    via+9        high byte of timer 2
  95. vacr    equ    via+11        auxiliary control register
  96. vpcr    equ    via+12        peripheral control register
  97. vifr    equ    via+13        interrupt flag register
  98. vier    equ    via+14        interrupt enable register
  99.  
  100. timrc1    equ    vtim1cl        both bytes of timer 1 counter
  101. timrl1    equ    vtim1ll        both bytes of timer 1 latch
  102. timer2    equ    vtim2l        both bytes of timer2 (counter and latch)
  103. v_int    equ    $20        timer2 interrupt bit (clear enable)
  104. vs_int    equ    $a0        timer2 interrupt bit (set enable)
  105. h_reset    equ    $ec        reset HDLC chip (via vpcr)
  106. h_oper    equ    $ee        operate HDLC chip (via vpcr)        
  107. t_cntl    equ    $c0        timer1=free run, timer2=interval, sr=off
  108.  
  109. ***        WD 1933 HDLC chip equates
  110. ***    IMPORTANT: this chip inverts Address and Data bits!!!
  111.  
  112. hdlc    equ    $2800        base address
  113. hcr1    equ    hdlc+7        control register 1
  114. hcr2    equ    hdlc+6        control register 2
  115. hcr3    equ    hdlc+5        control register 3
  116. hrhr    equ    hdlc+4        receive holding register
  117. hthr    equ    hdlc+3        transmit holding register
  118. hir    equ    hdlc+3        interrupt register
  119. hsr    equ    hdlc+2        status register
  120.  
  121. fflags    equ    $01        cr2 - send flags between frames
  122.  
  123. actrcv    equ    $80        activate receiver
  124. actran    equ    $40        activate transmitter
  125. actdtr    equ    $02        turn on DTR
  126. actptt    equ    $01        activate PTT line (misc. out)
  127.  
  128. txon    equ    actran+actdtr+actptt    preamble and data transmission
  129. rcvon    equ    actrcv+actdtr        receiving
  130. h_data    equ    $00+txon    Transmit commands
  131. h_abort    equ    $10+txon
  132. h_flag    equ    $20+txon
  133. h_fcs    equ    $30+txon    (sends fcs + flag)
  134. h_MASK    equ    $cf
  135.  
  136. reom    equ    $80        intreg - receive complete with no error
  137. reomerr    equ    $40        intreg - receive with error
  138. xcom    equ    $20        intreg - xmt command complete
  139. xcomerr    equ    $10        intreg - xmt error (underrun)
  140. dscchg    equ    $08        intreg - CD line state change
  141. drqi    equ    $04        intreg - input character available
  142. drqo    equ    $02        intreg - output character needed
  143. intrq    equ    $01        intreg - set if any of bits 3-7 are new
  144.  
  145. CD    equ    $40        status - location of CD state bit
  146.  
  147. ram    equ    $0000        bank 0 ram ($0000 - $1fff)
  148. hiram    equ    ram+8192    top of bank 0 ram
  149. ram1    equ    $4000        bank 1 ram ($4000 - $5fff) [not used]
  150. rom    equ    $e000        top rom    ($e000 - $ffff)
  151.  
  152. FEND    equ    @300        frame end
  153. FESC    equ    @333        frame escape
  154. TFEND    equ    @334        transposed frame end
  155. TFESC    equ    @335        transposed frame escape
  156.  
  157. CCZ    equ    $04        zero flag in CC
  158. CCNZ    equ    $fb        non-zero flag in CC
  159. NOT    equ    $ff        for negations
  160.  
  161. *
  162.     dsect
  163.  
  164.     org    ram        data starts in low ram
  165.  
  166. * for those who want to move this code to ROM:
  167. *
  168. * 1. The interrupt re-vector area must be moved to fff0-ffff
  169. *    Unused interrupts should be vectored to 'main'
  170. *
  171. * 2. DEBUG should be off (it has no use if TNCBUG is not around)
  172. *
  173. * 3. The RAM area must be initialized 'by hand' rather than by 'fcb'
  174. *
  175. * 4. The 6551 UART must be set up (TNCBUG does this now)
  176.  
  177. * interrupt re-vector area: parallel to fff0-ffff
  178.  
  179. igo    fdb    main        0000 - program start point
  180. iswi3    rmb    2        0002
  181. iswi2    rmb    2        0004
  182. ifirq    rmb    2        0006
  183. iirq    fdb    action        0008
  184. iswi    rmb    2        000a
  185. inmi    rmb    2        000c - last vector used
  186. ireset    rmb    2        full reset
  187.  
  188. stack    equ    $100        my stack is above debug stack
  189.     org    $100        local data starts at direct page 1
  190.  
  191. ***        Local Variables
  192.  
  193. p_speed    fcb    0        processor speed: 0= 1 Mhz, 1= 2 Mhz
  194. h_speed    fcb    4        (* 300) baud on hdlc
  195. u_txdly    fcb    6        tx start delay (* 10 ms)
  196. u_pers    fcb    128        persistence parameter
  197. u_slot    fcb    10        slot time delay (* 10 ms)
  198. u_tail    fcb    2        tx tail hold time (* 10 ms)
  199.  
  200. c_txdly    rmb    2        count value for txdelay
  201. c_slot    rmb    2        count value for slot delay
  202. c_tail    rmb    2        count value for tail delay
  203.  
  204. cdval    fcb    CD        last CD status value (CD on)
  205. fxflag    fcb    0        0 = hdx, 1 = fdx
  206. rand    rmb    1        pseudo-random value (0 <= rand <= 255)
  207. savhc    rmb    1        last hdlc command saved here
  208. svhir    rmb    1        HDLC interrupt status saved here
  209. temp    rmb    2
  210. tempih    rmb    1        temp used by interrupt handler only
  211. upper_t    rmb    1        upper 8 bits of 24 bit timer
  212. xmtok    fcb    0        xmit flag: 0= rcv, +1= xmit ok, -1= xmit
  213.  
  214. *        interrupt routine state information - initial values set
  215.  
  216. ARCV    fdb    await        acia receiver state
  217. AXMIT    fdb    asend        acia transmitter state
  218. HRCV    fdb    hkillb        hdlc receiver state
  219. HXMIT    fdb    hsend        hdlc transmitter state
  220. TIMACT    fdb    0        timer action state (after counted to zero)
  221.  
  222. *        i/o buffers
  223. *
  224. *    this is a circular buffer system, with the buffer extending from
  225. *    [FIRST] to [LIMIT-1].  IN is the real data in pointer.  When the
  226. *    block is accepted, AIN is updated to the value of IN.
  227.  
  228. FIRST    equ    0        pointer offsets for buffer header
  229. IN    equ    2
  230. AIN    equ    4        accepted data, IN pointer
  231. OUT    equ    6
  232. LIMIT    equ    8
  233.  
  234. cmdsize    equ    20        buffer for kiss control commands
  235. command    FDB    cmdbuf,cmdbuf,cmdbuf,cmdbuf,cmdbuf+cmdsize
  236.  
  237. *    buffer from acia to hdlc
  238. abufh    FDB    inbufend,inbufend,inbufend,inbufend,hiram
  239.  
  240. *    buffer from hdlc to acia
  241. hbufa    FDB    inbuffer,inbuffer,inbuffer,inbuffer,inbufend
  242.  
  243. cmdbuf    rmb    cmdsize        command buffer here, others at end of memory
  244.     pag
  245.  
  246. ***        Main program
  247. *
  248. *    Entered from 'G' command in debugger.
  249. *    At this time, the 6251 UART speed is set properly, do not reset it.
  250.  
  251. main    orcc    #$50        turn off interrupts (FIRQ + IRQ)
  252.     lda    #1
  253.     tfr    A,DP        set base page register to our variables
  254.     lds    #stack        set stack to our local stack
  255.  
  256. * disable UART
  257.     lda    #ac_dis        turn off receiver, set RTS only
  258.     sta    accmnd
  259.  
  260. * reset 6520        Not used by this program
  261.     clra
  262.     sta    pcra        disable pia-A
  263.     sta    pcrb        disable pia-B
  264.  
  265. * reset 6522        NOVROM is not used, only timers are used
  266.     lda    #h_reset
  267.     sta    vpcr        clear CA2 to reset HDLC chip
  268.     lda    #t_cntl
  269.     sta    vacr        reset 6522 timer and shift register
  270.     lda    #$f0
  271.     sta    vora        set A output bits to '1'
  272.     sta    vddra         turning off NOVROM access
  273.     lda    #$bf
  274.     sta    vorb        set B output bits to '1'
  275.     sta    vddrb         driving NOVROM address to all 1's
  276.     lda    #$7f
  277.     sta    vier        disable all 6522 interrupts
  278.     sta    vifr        clear all 6522 interrupts
  279.     lda    #$h_oper    clear HDLC reset bit, operate mode
  280.     sta    vpcr        reset 6522 control modes (CB2=1, CA2=1)
  281.  
  282. * preset
  283.     jsr    setdelay    compute delay counter values
  284.     lda    #CD        pretend CD set upon entry
  285.     sta    <cdval
  286.  
  287. * setup hdlc chip
  288. * first, wait for at least 2.5 TC cycles...
  289.     ldb    #3*32        2.5 to 3 cycles
  290. pw.0    lda    vorb
  291.     bmi    pw.0        wait for 0
  292. pw.1    lda    vorb
  293.     bpl    pw.1        wait for 1 (1/2 cycle)
  294.     decb
  295.     bne    pw.0
  296.  
  297.     clra
  298.     sta    <savhc
  299.     coma
  300.     sta    hcr3        no transmit residue
  301.     sta    hcr2        8-bit characters, no address comp
  302. **
  303.     lda    #ac_xmt        turn on acia, set RTS
  304.     sta    accmnd
  305.  
  306.     lda    #FEND        start host
  307.     sta    acchar
  308.  
  309.     lda    #rcvon        start hdlc receiver
  310.     tst    <fxflag
  311.     beq    hdon        half duplex
  312.     ldb    #fflags        turn on auto-flag
  313.     comb
  314.     stb    hcr2
  315.     ldx    #hfdxs
  316.     stx    HXMIT        state to begin full duplex ops
  317.     ldb    #1
  318.     stb    <xmtok        transmit is always ok
  319.     ora    #actptt        activate ptt
  320. hdon    sta    <savhc
  321.     coma
  322.     sta    hcr1
  323.  
  324.     jsr    hdsc        check current CD state
  325.  
  326.     cli            TURN ON INTERRUPTS
  327.     pag
  328. ***        Main loop, non-interrupt mode
  329.  
  330. loop    ldy    #command    look for commands
  331.     jsr    getbuf
  332.     bne    lpax        no command
  333.     tab
  334.     jsr    getbuf        get second command byte
  335.     sta    <temp
  336.     jsr    getbuf        must be FEND
  337.     cmpa    #FEND
  338.     bne    badcmd        bad command, kill it
  339.     lda    <temp
  340.  
  341. lp.1    decb            tx delay
  342.     bne    lp.2
  343.     sta    <u_txdly
  344.     bra    recomp        recompute delays
  345.  
  346. lp.2    decb            persistence
  347.     bne    lp.3
  348.     sta    <u_pers
  349.     bra    lpax
  350.  
  351. lp.3    decb            slot time
  352.     bne    lp.4
  353.     sta    <u_slot
  354.     bra    recomp
  355.  
  356. lp.4    decb            tx tail
  357.     bne    lp.5
  358.     sta    <u_tail
  359.     bra    recomp
  360.  
  361. lp.5    decb            hdx/fdx
  362.     bne    lp.6
  363.     cmpa    <fxflag        is this a change?
  364.     beq    lp.6        no
  365.     sta    <fxflag
  366.     jmp    main        ** major upheaval - restart **
  367.  
  368. lp.6    decb            baud rate and processor speed
  369.     bne    lpax        ..unrecognized
  370.     anda    #$7f        baud rate
  371.     sta    <h_speed
  372.     lda    <temp
  373.     anda    #$80        for TNC1 - fast processor flag
  374.     sta    <p_speed
  375. recomp    jsr    setdelay    recompute delays and baud rate
  376.     bra    lpax
  377.  
  378. badcmd    jsr    getbuf        purge command buffer
  379.     bne    lpax        buffer empty
  380.     cmpa    #FEND
  381.     bne    badcmd
  382.  
  383. * if the acia is idle, but with interrupts enabled, the TXempty bit is 0
  384. * so we can't check that...
  385. lpax    lda    accmnd        is acia transmitter running
  386.     cmpa    #ac_xmt
  387.     beq    lpah        yes
  388.     ldy    #hbufa        is there data to send
  389.     ldx    AIN,Y
  390.     cpx    OUT,Y
  391.     beq    lpah        no
  392. **
  393.     sei            turn off interrupts
  394.     lda    accmnd
  395.     cmpa    #ac_xmt
  396.     beq    lpac        cant start if acia running
  397.     jsr    [AXMIT]        start the acia transmitter
  398. lpac    cli            turn on interrupts
  399. **
  400.  
  401. * check for transmit data to HDLC line in a similar fashion
  402. lpah    tst    <xmtok        OK to go?
  403.     ble    lplp        no
  404.     ldy    #abufh
  405.     ldx    AIN,Y        is there data to send
  406.     cpx    OUT,Y
  407.     beq    lplp        no
  408. **
  409.     sei            repeat test with interrupts off
  410.     tst    <xmtok
  411.     ble    lpnh
  412.     ldy    #abufh
  413.     ldx    AIN,Y
  414.     cpx    OUT,Y
  415.     beq    lpnh
  416.     jsr    [HXMIT]        start the hdlc transmit process
  417. lpnh    cli            turn interrupts back on
  418. **
  419.  
  420. lplp    jmp    loop
  421.     pag
  422.  
  423. ***    Interrupt Handler - main code
  424.  
  425. action    lda    acstat        first check for acia activity
  426.     bpl    chkh        none, check hdlc
  427.     bita    #as_rdr        is there any receive data
  428.     beq    chkax        no, check transmit
  429.  
  430.     jsr    [ARCV]        acia receive action
  431.     lda    acstat
  432.     bpl    chkh        no transmit action
  433.  
  434. chkax    bita    #as_xmt        is transmitter empty
  435.     beq    chkh        no
  436.  
  437.     jsr    [AXMIT]        acia transmitter action
  438.  
  439. chkh    lda    hir        HDLC interrupt register
  440.     coma
  441.     bita    #intrq
  442.     bne    chkh.1        upper bits are significant
  443.     anda    #drqo+drqi    only data bits are significant
  444.     beq    cktim        nothing, check timer
  445. chkh.1    sta    <svhir        save it, since chip is now reset
  446.     bita    #drqi+reom+reomerr    is there receiver status
  447.     beq    chkhx        no receive action
  448.  
  449.     jsr    [HRCV]        perform receiver action
  450.     lda    <svhir
  451.  
  452. chkhx    bita    #drqo+xcom+xcomerr    is there transmitter status
  453.     beq    chkhs        no transmitter action
  454.  
  455.     jsr    [HXMIT]        perform transmitter action
  456.     lda    <svhir
  457.  
  458. chkhs    bita    #dscchg        data set change
  459.     beq    cktim        none, check timer
  460.  
  461.     jsr    hdsc        perform data set change action
  462.  
  463. cktim    lda    vifr        6522 interrupt flag register
  464.     bpl    xint        no timer interrupt
  465.  
  466.     jsr    dotime        handle timer
  467.  
  468. xint    rti            exit interrupt main loop
  469.     pag
  470.  
  471. ***    Interrupt Action Routines
  472.  
  473. ***        ACIA receiver actions
  474.  
  475. gowait    ldy    #ARCV
  476.     jsr    xstate
  477.  
  478. await    equ    *        State - wait for FEND
  479.     ldb    acchar        read character
  480.     bita    #as_err        check for receiver errors
  481.     bne    cstate        yes, continue waiting (same state)
  482.     cmpb    #FEND        is this the start of a frame
  483.     bne    cstate        no, continue waiting (same state)
  484.  
  485. agetcom    ldy    #ARCV        get block type byte
  486.     jsr    xstate        step state
  487.     ldb    acchar        read command character
  488.     bita    #as_err        check for receiver errors
  489.     bne    gowait        yes, resync on FEND
  490.     tstb            is command 00
  491.     beq    agetdat        yes, get data
  492.     cmpb    #DEBUG        ** if DEBUG is defined, stop here
  493.     bne    dea
  494.     swi
  495.     bra    gowait
  496. dea    nop
  497.     cmpb    #FEND        extra FEND?
  498.     beq    cstate        yes, ignore it (stay in this state)
  499.     tba
  500.     ldy    #command
  501.     jsr    putbuf
  502.     bne    gowait        putbuf failed, ignore command, sorry!
  503.  
  504. abldcmd    ldy    #ARCV        build command
  505.     jsr    xstate
  506.     ldy    #command    command buffer area
  507.     bra    abuild
  508.  
  509. cstate    rts            stay in current state
  510.  
  511. agetdat    ldy    #ARCV        get data
  512.     jsr    xstate
  513.     ldy    #abufh        data buffer area
  514.  
  515. abuild    ldb    acchar        read next byte
  516.     bita    #as_err        check for receiver errors
  517.     bne    adumpc        yes, dump data gathered so far
  518.     tba
  519.     jsr    putbuf        add byte to buffer
  520.     bne    adumpc        putbuf failed, dump data
  521.     cmpa    #FEND        last byte?
  522.     bne    cstate        no, continue to gather data
  523.     ldx    IN,Y        accept data
  524.     stx    AIN,Y
  525.     bra    agetcom        next byte should be command again
  526.  
  527. adumpc    ldx    AIN,Y        dump accumulation of data
  528.     stx    IN,Y
  529.     cmpa    #FEND        was failure on last byte
  530.     bne    gowait        no, wait for FEND
  531.     bra    agetcom        yes, get command again
  532.     pag
  533.  
  534.  
  535. ***        ACIA transmitter actions
  536.  
  537. axsend    ldy    #AXMIT
  538.     jsr    xstate
  539. asend    equ    *        Transmitter active on entry
  540.     ldy    #hbufa
  541.     jsr    getbuf        get next character to send to host
  542.     bne    axnone        none, turn off transmit
  543.     sta    acchar        send the char
  544.     rts            stay in this state
  545.  
  546. axnone    lda    #ac_enb        turn off transmit interrupts
  547.     sta    accmnd
  548.     ldy    #AXMIT
  549.     jsr    xstate
  550.  
  551.     ldy    #hbufa        attempt to restart transmitter
  552.     jsr    getbuf
  553.     bne    cstate        no character, dont start
  554.     ldb    #ac_xmt        re-enable interrupt
  555.     stb    accmnd
  556.     sta    acchar        send the character
  557.     bra    axsend        flip to other state
  558.     pag
  559.  
  560.  
  561. ***        HDLC receive actions
  562.  
  563. hkillr    lda    <savhc
  564.     anda    #NOT-actrcv    disable receive if enabled
  565.     coma
  566.     sta    hcr1
  567.     lda    <savhc        re-enable receive if enabled
  568.     coma
  569.     sta    hcr1        (should cause 'hunt' action)
  570.  
  571. hkillb    ldy    #hbufa        kill receive block
  572.     ldx    AIN,Y
  573.     stx    IN,Y
  574. gohrec    clra            first byte indicates DATA block
  575.     jsr    putbuf
  576.  
  577.     ldy    #HRCV
  578.     jsr    xstate
  579.  
  580. hrec    equ    *        receive characters here
  581.     bita    #drqi        do we have a character
  582.     beq    hrckend        no, check end cases
  583.     ldy    #hbufa        receive buffer
  584.     lda    hrhr        receive character
  585.     coma
  586.     cmpa    #FEND        check special cases
  587.     beq    hrec.1
  588.     cmpa    #FESC
  589.     bne    hrec.2        ordinary character
  590.     ldb    #TFESC
  591.     bra    hrec.1a
  592. hrec.1    ldb    #TFEND
  593. hrec.1a    lda    #FESC
  594.     jsr    putbuf        put character in buffer
  595.     bne    hkillr        buffer full
  596.     tba
  597. hrec.2    jsr    putbuf        put character in buffer
  598.     bne    hkillr        buffer full
  599.     lda    <svhir
  600.     bita    #reom        was this also end of message
  601.     bne    hreom
  602.     bita    #reomerr    was this also an error end
  603.     bne    hkillb
  604.     rts            continue (stay in this state)
  605.  
  606. hrckend    bita    #reom        normal end
  607.     beq    hkillb        no, kill receive block
  608.  
  609. * The WD chip has read in the bcc before giving us the eom indication.
  610. *  We must back over it
  611.  
  612. hreom    ldy    #hbufa
  613.     jsr    back2        back up 2 characters
  614.     bne    hkillb        (system) error in backing
  615.     lda    #FEND
  616.     jsr    putbuf
  617.     bne    hkillb        buffer full
  618.     ldx    IN,Y        accept data
  619.     stx    AIN,Y
  620.     bra    gohrec        set to receive next block
  621.     pag
  622.  
  623.  
  624. ***        HDLC transmit actions
  625.  
  626. gohsend    ldy    #HXMIT
  627.     jsr    xstate
  628.  
  629. hsend    equ    *        initial transmit state
  630.     lda    #-1        signal transmit active
  631.     sta    <xmtok
  632.     tst    <fxflag        is this full duplex
  633.     bne    hstart        yes, start sending immediately
  634.     lda    <savhc
  635.     anda    #NOT-actrcv    turn off receiver if half duplex
  636.     sta    <savhc
  637.     ldx    <c_txdly    pre-xmit delay
  638.     beq    hstart        no delay
  639.     clra            pre-start, send zeros for sync
  640.     coma             (this gives faster DPLL lockup)
  641.     sta    hthr
  642.     lda    #h_data        send data
  643.     jsr    setcr1
  644.     ldd    <c_txdly    start timer
  645.     ldx    #hset1
  646.     jsr    settime
  647.  
  648.     ldy    #HXMIT        pre-start state, just send more zeros
  649.     jsr    xstate
  650.     bita    #drqo        check for normal entry
  651.     lbeq    hxabt        abort, abnormal termination
  652.     clra
  653.     coma
  654.     sta    hthr        send another zero
  655.     rts            stay in this state until timer runs out
  656.  
  657. **
  658. hset1    ldx    #hstart        Timer action: start block
  659.     stx    HXMIT
  660.     rts
  661. **
  662.  
  663. hstart    ldy    #abufh
  664.     jsr    getbuf        get first character of frame
  665.     coma
  666.     sta    hthr         this prevents DRQO interrupts...
  667.     tst    <fxflag        is this full duplex
  668.     bne    hsdat        yes, can go immediately
  669.     lda    #h_flag        if half duplex, send leading flag
  670.     bra    hsgo
  671.  
  672. hfdxs    lda    #-1        initial full duplex start
  673.     sta    <xmtok
  674.     lda    <savhc
  675.     ora    #actran        turn on transmitter..
  676.     sta    <savhc
  677.     coma
  678.     sta    hcr1
  679.     bra    hsendc        wait for DRQO and start
  680.  
  681. hendf    lda    #h_fcs        send fcs + done
  682.     bra    hxab.E
  683.  
  684. hfcs    jsr    getbuf        is there another frame
  685.     bne    hendf        no
  686.     cmpa    #FEND        is this a null frame
  687.     beq    hfcs        yes, skip it
  688.     sta    hthr        load first character of next frame..
  689.     lda    #h_fcs
  690.  
  691. hsgo    jsr    setcr1        send flag or fcs before frame
  692.  
  693.     ldy    #HXMIT
  694.     jsr    xstate        set next state
  695.  
  696.     bita    #xcom
  697.     beq    hxabt        abort on error
  698. hsdat    lda    #h_data        put us into data mode for frame
  699.     jsr    setcr1         (first character goes now...)
  700.  
  701.     ldy    #HXMIT
  702.     jsr    xstate
  703.  
  704. hscont    ldy    #abufh
  705.     jsr    getbuf        get next character
  706.     bne    hxab.H        out of data, without FEND (internal error)
  707.     cmpa    #FESC        escape
  708.     bne    hsenda        ordinary character
  709.     jsr    getbuf        get character following FESC
  710.     tab
  711.     lda    #FEND
  712.     cmpb    #TFEND
  713.     beq    hsendb
  714.     lda    #FESC        these are all of the cases (today)
  715.     cmpb    #TFESC
  716.     beq    hsendb
  717.     tba            recover character, invalid escape
  718. hsenda    cmpa    #FEND
  719.     beq    hfcs        done, send fcs
  720. hsendb    coma
  721.     sta    hthr        send character
  722.  
  723. hsendc    ldy    #HXMIT
  724.     jsr    xstate        set next state
  725.  
  726.     bita    #xcomerr    error sending
  727.     beq    hscont        continue if no error
  728.  
  729. hxabt    ldy    #abufh        error sending, scrap entire message
  730. hxab.1    jsr    getbuf
  731.     bne    hxab.H
  732.     cmpa    #FEND
  733.     bne    hxab.1
  734. hxab.H    lda    #h_abort
  735.  
  736. hxab.E    jsr    setcr1        send the abort or fcs at end
  737.  
  738.     ldy    #HXMIT
  739.     jsr    xstate
  740.  
  741.     ldd    <c_tail        post-xmit timer
  742.     beq    hxdone        no waiting
  743.     ldx    #hxdone
  744.     jsr    settime        start tail timer
  745.     ldy    #HXMIT
  746.     jsr    xstate
  747.  
  748.     clra
  749.     coma
  750.     sta    hthr        make DRQO interrupts go away
  751.     rts            return - no interrupts until timer done
  752.  
  753. hxdone    lda    #1        not transmitting
  754.     sta    <xmtok
  755.     tst    <fxflag        full duplex?
  756.     bne    hxd.1        yes, don't turn off ptt
  757.  
  758.     lda    <savhc
  759.     anda    #NOT-actran-actptt    turn off transmitter
  760.     ora    #actrcv        turn on receiver
  761.     sta    <savhc
  762.     coma
  763.     sta    hcr1
  764.     clr    <xmtok        receiving flag
  765.     lda    #CD
  766.     sta    <cdval        re-examine CD state
  767.     bsr    hdsc
  768.  
  769. hxd.1    jmp    gohsend        return to starting state
  770.     pag
  771.  
  772.  
  773. ***        Carrier-sense change handler
  774.  
  775. hdsc    lda    hsr        read status register
  776.     tst    <fxflag        are we full duplex?
  777.     bne    hdrts        yes, no action needed
  778.     coma
  779.     anda    #CD        look at CD bit
  780.     cmpa    <cdval        compare with saved value
  781.     beq    hdrts        same, no action
  782.     sta    <cdval        save new value
  783.     beq    hdsoff        now off
  784.  
  785.     tst    <xmtok        hdx - are we transmitting now?
  786.     bmi    hdrts        yes, will turn on at end of xmit
  787.     clr    <xmtok        set state to receiving
  788.     lda    #v_int
  789.     sta    vier        disable timer2 interrupt, if active
  790.     ldd    timer2
  791.     lda    <savhc
  792.     ora    #actrcv        turn on receiver
  793.     sta    <savhc
  794.     coma
  795.     sta    hcr1
  796. hdrts    rts            return
  797.  
  798. hdsoff    lda    <savhc        turn off receiver if carrier drops
  799.     anda    #NOT-actrcv
  800.     sta    <savhc
  801.     coma
  802.     sta    hcr1
  803.     jsr    hkillr        kill any receive block in progress
  804.     tst    <xmtok        are we transmiting?
  805.     bne    hdrts        yes, if half duplex this is false indication
  806.     bra    pwait        always wait 1 slot time at least...
  807.  
  808. persist    jsr    getran        get a random number
  809.     cmpb    <u_pers        compare against persistence value
  810.     bls    setxok        ok to transmit
  811. pwait    ldd    <c_slot        no, wait 'slot' time and retry
  812.     ldx    #persist
  813.     bra    settime        start timer
  814.  
  815. setxok    lda    #1        ok to transmit now
  816.     sta    <xmtok
  817.     rts
  818.     pag
  819.  
  820.  
  821. ***        Timer handling
  822.  
  823. dotime    ldd    timer2        clear timer interrupt and read timer
  824.     tst    <upper_t
  825.     beq    tdone        timer expired
  826.     dec    <upper_t
  827.     tsta
  828.     bne    dot.1        correct for nn00 to (nn-1)ff
  829.     incb
  830. dot.1    std    timer2        reenable interrupt
  831.     rts            done with timer
  832.  
  833. tdone    lda    #v_int        timer2 interrupt bit
  834.     sta    vier        disable interrupt
  835.     lda    timer2
  836.     jmp    [TIMACT]    do timer action
  837.     pag
  838.  
  839.  
  840. ***    Interrupt Support Subroutines
  841.  
  842. * SETCR1 - set type of transmit in hcr1 - done often
  843. *
  844. *    entry:    A = new data/flag/abort type to set
  845. setcr1    sta    <tempih
  846.     lda    <savhc
  847.     anda    #h_MASK
  848.     ora    <tempih
  849.     sta    <savhc
  850.     coma
  851.     sta    hcr1
  852.     rts
  853.  
  854. * SETTIME - start timer with specified action
  855. *
  856. *    entry:    D = upper 16 bits of 24 bit timer value
  857. *        X = location of timer action routine
  858. *
  859. settime    stx    TIMACT        store action address
  860.     sta    <upper_t    upper 8 bit of timer value
  861.     clra
  862.     tstb            is timer value 0 mod 65536
  863.     bne    sett.1        no
  864.     dec    <upper_t    yes, tick over one count
  865.     bmi    tdone        all zero count, finish immediately
  866.     coma
  867.     comb            set D = $ffff
  868. sett.1    std    timer2        start timer with residual mod 65536
  869.     lda    #vs_int        enable timer2 interrupt
  870.     sta    vier
  871.     rts
  872.  
  873. * XSTATE - set new state for interrupt task
  874. *
  875. *    entry:    address of state jump word in Y
  876. *
  877. xstate    puls    X        get return address into X
  878.     stx    0,Y        save it as state address
  879.     rts            return to state caller
  880.     pag
  881.  
  882.  
  883. ***    General Subroutines
  884.  
  885. * GETBUF, PUTBUF - handle getting or putting characters from/to buffers
  886. *
  887. *    entry:    buffer head address in Y
  888. *    exit:    zero flag set if all is well, NZ otherwise (overflow or empty)
  889. *
  890. getbuf    ldx    OUT,Y        get the OUT pointer
  891.     cpx    AIN,Y        check for data present
  892.     beq    nobuf        no data, set NZ and exit
  893.     lda    0,X        get the data
  894.     bsr    incbuf        increment pointer value
  895.     stx    OUT,Y        new pointer
  896. yesbuf    orcc    CCZ        set Z flag
  897.     rts
  898.  
  899. putbuf    ldx    IN,Y        get the IN pointer
  900.     tfr    X,U        save it in a convenient place
  901.     bsr    incbuf        next value of IN
  902.     cpx    OUT,Y        is the buffer full
  903.     beq    nobuf        yes, operation fails
  904.     sta    0,U        no, store the data
  905.     stx    IN,Y        new pointer
  906.     bra    yesbuf
  907.  
  908. nobuf    andcc    CCNZ        clear Z flag
  909.     rts
  910.  
  911. incbuf    inx            increment pointer
  912.     cpx    LIMIT,Y        at limit
  913.     bne    incrts        no
  914.     ldx    FIRST,Y        yes, wrap to first
  915. incrts    rts
  916.  
  917. * BACK2 - back up in buffer -- used to back up over bcc received
  918. *
  919. *    entry:    buffer head address in Y
  920. *
  921. *  A good block should leave at least 2 data characters plus the bcc
  922. *   in the buffer.  The backup algorithm takes advantage of this
  923. *   when over-backing to check for FESC
  924. *
  925.  
  926. back2    ldx    IN,Y
  927.     cpx    AIN,Y
  928.     beq    nobuf        whoops.. shouldn't happen (system error)
  929.     bsr    back1
  930.     bne    incrts        error
  931.     bsr    back1
  932.     bne    incrts        error
  933.     stx    IN,Y
  934.     bra    yesbuf        no error
  935.  
  936. back1    bsr    decbuf        back up
  937.     bne    incrts        hit old AIN
  938.     bsr    decbuf
  939.     bne    incrts
  940.     lda    0,X
  941.     cmpa    #FESC
  942.     beq    yesbuf        2 back was FESC, so 1 back was escaped
  943.     bsr    incbuf        1 back was good
  944.     bra    yesbuf
  945.  
  946. decbuf    cpx    FIRST,Y
  947.     bne    decb.1
  948.     ldx    LIMIT,Y
  949. decb.1    dex
  950.     cpx    AIN,Y
  951.     bne    yesbuf        ok, not at AIN
  952.     bra    nobuf        whoops.. shouldn't happen (system error)
  953.     
  954. * GETRAN - get a random number in B
  955. *
  956. *    uses mixed congruential generator: X' = 21*X + 53
  957. *
  958. getran    lda    #21
  959.     ldb    <rand        previous value
  960.     mul
  961.     addb    #53
  962.     stb    <rand
  963.     rts
  964.  
  965. * SETDELAY - compute delay values and set baud rate counter
  966. *
  967. setdelay ldb    #36        = 921600 / 256 (* .01 seconds)
  968.     tst    <p_speed    is this a fast processor/counter
  969.     beq    .setd1        no
  970.     aslb            yes, double the count required
  971. .setd1    stb    <temp
  972.     lda    <u_txdly    units of tx delay
  973.     mul
  974.     std    <c_txdly
  975.     ldb    <temp
  976.     lda    <u_slot        units of slot delay
  977.     mul
  978.     std    <c_slot
  979.     ldb    <temp
  980.     lda    <u_tail        units of tx tail delay
  981.     mul
  982.     std    <c_tail
  983.  
  984.     tst    <h_speed    speed requested for hdlc
  985.     bne    .seth1        legal speed requested
  986.     lda    #4        default to 1200 on error
  987.     sta    <h_speed
  988. .seth1    ldb    #96        = 300 baud at fast processor clock
  989.     clra
  990. .seth2    inca
  991.     subb    <h_speed
  992.     bgt    .seth2        divide 96 by multiple of 300 baud desired
  993.     tst    <p_speed    now check processor speed
  994.     bne    .seth3        fast
  995.     lsra            slow, divide result by 2
  996. .seth3    suba    #2        counter always takes 2 more per half cycle
  997.     bmi    .seth4        too fast, ignore request
  998.     clrb
  999.     std    timrc1        store baud rate in timer 1 COUNTER to start it
  1000. .seth4    rts
  1001.  
  1002.  
  1003. ***
  1004. progend    equ    *        input buffer starts here
  1005. inbuffer rmb    2049
  1006. inbufend equ    *        output buffer starts here
  1007.  
  1008.     end
  1009.  
  1010.  
  1011.